#pragma once
#include <bits/stdint-uintn.h>
#include <boost/date_time/posix_time/ptime.hpp>
#include <iostream>
#include <memory>
#include <string>
#include <cstddef>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <odb/nullable.hxx>
#include <odb/core.hxx>

namespace MessageFields {
    constexpr const char* SESSION_ID = "sessionId";
    constexpr const char* MESSAGE_ID = "messageId";
    constexpr const char* USER_ID = "userId";
    constexpr const char* CREATE_TIME = "createTime";
    constexpr const char* CONTENT = "content";

    constexpr const char* SESSION_ID_KEYWORD = "sessionId.keyword";
}

namespace entity {

#pragma db object table("message")
class Message 
{
public:
    Message() {}
    Message(const std::string& msgId, const std::string& sid, const std::string& uid,
        const uint8_t msgType, const boost::posix_time::ptime& createTime)
        : messageId_(msgId), sessionId_(sid), userId_(uid)
        , messageType_(msgType), createTime_(createTime) {}

    // void setBaseInfo(const std::string& chatSessionId, const im_proto::UserInfo& userInfo)

    void setMessageId(const std::string& val) { messageId_ = val; }
    std::string messageId() const { return messageId_; }

    void setSessionId(const std::string& val) { sessionId_ = val; }
    std::string sessionId() const { return sessionId_; }

    void setUserId(const std::string& val) { userId_ = val; }
    std::string userId() const { return userId_; }

    void setMessageType(const uint8_t val) { messageType_ = val; }
    uint8_t messageType() const { return messageType_; }

    void setCreateTime(const boost::posix_time::ptime& val) { createTime_ = val; }
    boost::posix_time::ptime createTime() const { return createTime_; }

    void setContent(const std::string& val) { content_ = val; }
    std::string content() const { return content_ ? *content_ : std::string(); }

    void setFileId(const std::string& val) { fileId_ = val; }
    std::string fileId() const { return fileId_ ? *fileId_ : std::string(); }

    void setFilename(const std::string& val) { filename_ = val; }
    std::string filename() const { return filename_ ? *filename_ : std::string(); }

    void setFileSize(const uint64_t val) { fileSize_ = val; }
    uint64_t fileSize() const { return fileSize_ ? *fileSize_ : 0; }

private:
    friend class odb::access; 
    
    #pragma db id auto
    uint32_t id_;

    #pragma db column("message_id") type("varchar(32)") index unique
    std::string messageId_;

    #pragma db column("session_id") type("varchar(32)") index
    std::string sessionId_;     // 消息所属会话

    #pragma db column("user_id") type("varchar(32)") index
    std::string userId_;        // 消息的发送者
    
    #pragma db column("message_type")
    uint8_t messageType_;       // 消息类型

    #pragma db column("create_time") type("TIMESTAMP")
    boost::posix_time::ptime createTime_;      // 消息的产生时间

    #pragma db null
    odb::nullable<std::string> content_;       // 消息正文

    #pragma db column("file_id") type("varchar(32)") null
    odb::nullable<std::string> fileId_;        
    
    #pragma db type("varchar(32)") null
    odb::nullable<std::string> filename_;        

    #pragma db column("file_size") null
    odb::nullable<uint64_t> fileSize_;       
};

using MessagePtr = std::shared_ptr<Message>;

}

// odb -d mysql --std c++11 --generate-query --generate-schema --profile boost/date-time message.hxx